package one.stand.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.jmp.base.dto.AccountCompanyIdRequest;
import com.jmp.base.dto.AccountResponse;
import com.jmp.feign.AccountFeign;
import com.jmp.feign.PayFeign;
import lombok.extern.slf4j.Slf4j;
import one.stand.code.RedisCode;
import one.stand.config.WxUrlConfig;
import one.stand.entity.OrderNoEntity;
import one.stand.enums.LoginEnum;
import one.stand.exception.GoPayException;
import one.stand.mapper.CompanyAccountMapper;
import one.stand.mapper.CompanyMapperExt;
import one.stand.mapper.CompanyRecruitMapper;
import one.stand.model.*;
import one.stand.request.CompanyAccountRequest;
import one.stand.request.CompanyRecruitRequest;
import one.stand.request.CompanyRequest;
import one.stand.request.WebsiteRequest;
import one.stand.response.CompanyRecruitResponse;
import one.stand.response.CompanyResponse;
import one.stand.service.CompanyService;
import one.stand.service.WebsiteService;
import one.stand.service.wx.WxPayService;
import one.stand.util.DateUtil;
import one.stand.util.OneConstant;
import one.stand.util.RedisUtil;
import one.stand.util.WxConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author Administrator
 */
@Service
@Slf4j
public class CompanyServiceImpl implements CompanyService {

    @Autowired
    private PayFeign payFeign;
    @Autowired
    private AccountFeign accountFeign;

    @Autowired
    private WebsiteService websiteService;
    @Autowired
    private CompanyMapperExt companyMapperExt;
    @Autowired
    private CompanyAccountMapper companyAccountMapper;
    /**
     * 公司招聘表
     */
    @Autowired
    private CompanyRecruitMapper companyRecruitMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public ResultModel<CompanyResponse> getCompanyId(CompanyRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        Company model = companyMapperExt.selectByUserId(request.getId().intValue());
        if (model == null) {
            return ResultModel.success(null);
        }
        CompanyResponse response = new CompanyResponse();
        BeanUtils.copyProperties(model, response);
        return ResultModel.success(response);

    }

    @Override
    public ResultModel<CompanyResponse> invitation(CompanyRequest request) {
        if (null == request.getCompanyId()) {
            return ResultModel.checkParamFail();
        }
        CompanyResponse response = companyMapperExt.crmCompany(request.getCompanyId().intValue());
        return ResultModel.success(response);
    }

    @Override
    public ResultModel<CompanyResponse> getCompany(CompanyRequest request) {
        CompanyModel model = new CompanyModel();
        if (request.getCompanyId() != null) {
            model.setCompanyId(request.getCompanyId());
        } else {
            model.setCompanyId(request.getCId().intValue());
        }
        if (request.getMyCardId() != null) {
            model.setCardId(request.getMyCardId().intValue());
        }
        CompanyResponse response = companyMapperExt.crmCompanyInfo(model);
        if (response != null && request.getMyCardId() != null) {
            response.setCardId(request.getMyCardId().intValue());
        }
        return ResultModel.success(response);
    }

    @Override
    public ResultModel getCompanyAllInfo(CompanyRequest request) {
        log.info("下拉查询公司参数：{}", JSON.toJSONString(request));
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        CompanyModel companyModel = new CompanyModel();
        companyModel.setCompanyName(request.getCompanyName());
        companyModel.setIsDel(0);
        companyModel.setAuditState(1);
        companyModel.setCompanyState(1);
        List<Company> list = companyMapperExt.selectAll(companyModel);
        if (list == null || list.size() <= 0) {
            return ResultModel.noData();
        }
        List<CompanyResponse> responseList = new ArrayList<>();
        list.forEach(cl -> {
            CompanyResponse companyResponse = new CompanyResponse();
            BeanUtils.copyProperties(cl, companyResponse);
            responseList.add(companyResponse);
        });
        return ResultModel.success(responseList);
    }

    @Override
    public ResultModel addWebsiteInfo(WebsiteRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        if (request.getWebsiteId() == null) {
            int r = websiteService.saveEmpty(request.getCId().intValue());
            if (r > 0) {
                return ResultModel.success();
            }
            return ResultModel.fail();
        }

        Website model = new Website();
        BeanUtils.copyProperties(request, model);
        model.setLatitude(request.getLatitude());
        model.setLongitude(request.getLongitude());
        model.setUpdateTime(DateUtil.currentDate());
        websiteService.update(model);
        return ResultModel.success(model.getWebsiteId());
    }

    @Override
    public ResultModel selectCompanyRecruit(CompanyRecruitRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        CompanyRecruitModel model = new CompanyRecruitModel();
        BeanUtils.copyProperties(request, model);
        model.setCompanyId(request.getCId().intValue());
        List<CompanyRecruitModel> list = companyRecruitMapper.select(model);
        if (list == null || list.size() <= 0) {
            return ResultModel.noData();
        }
        List<CompanyRecruitResponse> responseList = new ArrayList<>();
        list.forEach(cl -> {
            CompanyRecruitResponse response = new CompanyRecruitResponse();
            BeanUtils.copyProperties(cl, response);
            responseList.add(response);
        });
        return ResultModel.success(responseList);
    }

    @Override
    public ResultModel addCompanyRecruit(CompanyRecruitRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        CompanyRecruitModel model = new CompanyRecruitModel();
        BeanUtils.copyProperties(request, model);
        int r;
        if (request.getRecruitId() == null || request.getRecruitId() <= 0) {
            model.setCompanyId(request.getCId().intValue());
            model.setIsDel(0);
            model.setCreateTime(DateUtil.currentDate());
            r = companyRecruitMapper.insertSelective(model);
        } else {
            r = companyRecruitMapper.updateByPrimaryKeySelective(model);
        }
        if (r > 0) {
            return ResultModel.success();
        }
        return ResultModel.fail();
    }

    @Override
    public ResultModel addHrPhone(CompanyRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        Company model = new Company();
        model.setCompanyId(request.getCId().intValue());
        model.setRecruitPhone(request.getRecruitPhone());
        int r = companyMapperExt.updateByPrimaryKeySelective(model);
        if (r > 0) {
            return ResultModel.success();
        }
        return ResultModel.fail();
    }

    @Override
    public ResultModel delCompanyRecruit(CompanyRecruitRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        }
        CompanyRecruitModel model = new CompanyRecruitModel();
        model.setRecruitId(request.getRecruitId());
        model.setIsDel(1);
        int r = companyRecruitMapper.updateByPrimaryKeySelective(model);
        if (r > 0) {
            return ResultModel.success();
        }
        return ResultModel.fail();
    }

    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private WxUrlConfig wxUrlConfig;

    @Override
    public ResultModel<String> payment(CompanyAccountRequest request) {
        log.info("配置支付信息：{}", JSON.toJSONString(request));
        if (request == null || request.getMerchantId() == null || StringUtils.isBlank(request.getKey()) || StringUtils.isBlank(request.getCertData())) {
            return ResultModel.checkParamFail();
        }
        try {
            WxConfig wxConfig = wxConfig(request.getCId().intValue());
            WXPay wxpay = new WXPay(wxConfig);
            String no = getPayNo();
            Map<String, String> data = new HashMap<>(12);
            data.put("appid", wxConfig.getAppID());
            data.put("mch_id", request.getMerchantId());
            data.put("nonce_str", no);
            data.put("body", "crmPc支付");
            data.put("out_trade_no", no);
            data.put("fee_type", "CNY");
            data.put("total_fee", "1");
            data.put("spbill_create_ip", request.getIp());
            data.put("notify_url", wxUrlConfig.getCrmPcBackUrl());
            data.put("trade_type", "MWEB");
            JSONObject sceneInfo = new JSONObject();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type", "WAP");
            jsonObject.put("wap_url", wxUrlConfig.getWapUrl());
            jsonObject.put("wap_name", "支付信息");
            sceneInfo.put("h5_info", jsonObject);
            data.put("scene_info", sceneInfo.toJSONString());
            log.info("微信支付返回：{}", JSON.toJSONString(data));
            data.put("sign", WXPayUtil.generateSignature(data, request.getKey()));
            Map<String, String> resp = wxpay.unifiedOrder(data);
            log.info("微信支付返回：{}", JSON.toJSONString(resp));
            if ("SUCCESS".equals(resp.get("return_code"))) {
                // redis 保存信息
                OrderNoEntity entity = new OrderNoEntity();
                entity.setKey(request.getKey());
                entity.setCertData(request.getCertData());
                entity.setMerchantId(request.getMerchantId());
                entity.setAccountId(wxConfig.getAccountId());
                redisUtil.set(RedisCode.getWxKey(no), entity);
                return ResultModel.success(resp.get("mweb_url"));
            }
        } catch (Exception e) {
            log.error("====", e);
        }
        return ResultModel.fail();
    }

    @Override
    public String backPayMent(String request) {
        log.info("CRM-PC微信支付回调：{}", request);
        Map<String, String> notifyMap;
        try {
            notifyMap = WXPayUtil.xmlToMap(request);
            String outTradeNo = notifyMap.get("out_trade_no");
            OrderNoEntity entity = redisUtil.get(RedisCode.getUserOrderKey(outTradeNo));
            if (entity != null) {
                WxConfig wxConfig = wxConfig(entity.getCompanyId());
                WXPay wxpay = new WXPay(wxConfig);
                if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
                    entity = redisUtil.get(RedisCode.getWxKey(outTradeNo));
                    if (entity == null) {
                        wxPayService.fail();
                    }
                    // 付款成功
                    if (OneConstant.SUCCESS.equals(notifyMap.get("return_code"))) {
                        redisUtil.remove(RedisCode.getWxKey(outTradeNo));
                        CompanyAccount model = new CompanyAccount();
                        model.setAccountId(entity.getAccountId());
                        model.setCertData(entity.getCertData());
                        model.setKey(entity.getKey());
                        model.setMerchantId(entity.getMerchantId());
                        companyAccountMapper.updateByPrimaryKeySelective(model);
                        return wxPayService.success();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("微信回调验证错误", e);
        }
        return wxPayService.fail();
    }

    /**
     * 根据时间戳生产退款订单编号
     *
     * @return
     */
    private static String getPayNo() {
        return "PAY" + System.currentTimeMillis() + "" + (int) (1 + Math.random() * (9999));
    }

    private WxConfig wxConfig(Integer companyId) throws GoPayException {
        AccountCompanyIdRequest accountCompanyIdRequest = AccountCompanyIdRequest.builder()
                .companyId(companyId)
                .loginEnum(LoginEnum.WX_PAY)
                .build();
        ResultModel<AccountResponse> accountResponseResultModel = accountFeign.getCompanyId(accountCompanyIdRequest);
        AccountResponse companyAccountModel = accountResponseResultModel.isSuccess() ? accountResponseResultModel.getData() : null;
        if (null == companyAccountModel) {
            log.info("未获取到公司账户{}", JSON.toJSONString(companyAccountModel));
            throw new GoPayException(JSON.toJSONString(companyAccountModel));
        }
        WxConfig wxConfig = new WxConfig();
        wxConfig.setAccountId(companyAccountModel.getAccountId());
        wxConfig.setAppId(companyAccountModel.getAppId());
        wxConfig.setKey(companyAccountModel.getKey());
        wxConfig.setMchId(companyAccountModel.getMerchantId());
        wxConfig.setCertData(Base64.getDecoder().decode(companyAccountModel.getCertData()));
        wxConfig.setNotifyUrl(wxUrlConfig.getNotifyUrl());
        wxConfig.setRefundUrl(wxUrlConfig.getRefundUrl());
        wxConfig.setHttpConnectTimeoutMs(5000);
        wxConfig.setHttpReadTimeoutMs(5000);
        return wxConfig;
    }
}